/*!
 * \file stomp_core.c
 *
 * \brief stomp解析
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * ct管理用共通函数
 *
 * \version 2.0
 * \author geyh
 * \date 2015/10/09
 *
 */
#include <stdio.h>
#include <string.h>
#include <sys/time.h>

#include "frcomm.h"
#include "frmem.h"

#include "frct_comm.h"

#include "stomp_comm.h"
#include "stomp_parse.h"

#include "stomp_core.h"
#include "../../lib/apmmodule/module_comm.h"

extern void *g_p_apm_context;
/*!
 * 判断是否是stomp协议
 *
 * \p_st_conn                    (输入数据信息)
 * \p_st_packet                 (输入数据)
 *
 * \return APM_L7_IS_NO:不属于TCP协议\n
 *         APM_L7_IS_YES:属于TCP协议
 *
 */
int stomp_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    char *p_data = NULL, *p_pos = NULL;
    int i_data_len = 0, i_ret_fun = 0;
    int i_tmp_len = 0, i_ret = FR_DIRECT_UNKNOWN;

    if(p_st_conn == NULL || p_st_packet == NULL || p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len == 0)
        return APM_L7_IS_NO;

    p_data = p_st_packet->p_payload;
    i_data_len = p_st_packet->ui_payload_len;

    p_pos = (char *)memchr(p_data, '\x0a', i_data_len);
    if(p_pos == NULL)
        return APM_L7_IS_NO;

    // CONNECTED  CONNECT SUBSCRIBE RECEIPT MESSAGE  ACK  UNSUBSCRIBE  DISCONNECT

    i_tmp_len = p_pos - p_data;
    switch(i_tmp_len)
    {
        case 3:
            if(strncmp(p_data, "ACK", 3) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else
                 return APM_L7_IS_NO;

            break;

        case 4:
            if(strncmp(p_data, "SEND", 4) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else if(strncmp(p_data, "NACK", 4) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else
                 return APM_L7_IS_NO;

            break;

        case 5:
            if(strncmp(p_data, "STOMP", 5) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else if(strncmp(p_data, "ABORT", 5) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else if(strncmp(p_data, "BEGIN", 5) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else if(strncmp(p_data, "ERROR", 5) == 0)
                i_ret = FR_DIRECT_SRV2CLIENT;
            else
                 return APM_L7_IS_NO;

            break;

        case 7:
            if(strncmp(p_data, "CONNECT", 7) == 0)
            {
                i_ret = FR_DIRECT_CLIENT2SRV;
            }
            else if(strncmp(p_data, "MESSAGE", 7) == 0)
            {
                i_ret = FR_DIRECT_SRV2CLIENT;
            }
            else if(strncmp(p_data, "RECEIPT", 7) == 0)
            {
                i_ret = FR_DIRECT_SRV2CLIENT;
            }
            else
                return APM_L7_IS_NO;

            break;

//        case 8:
//            if(strncmp(p_data, "SHUTDOWN", 8) == 0)
//                i_ret = FR_DIRECT_CLIENT2SRV;
//
//            break;

        case 9:
            if(strncmp(p_data, "CONNECTED", 9) == 0)
                i_ret = FR_DIRECT_SRV2CLIENT;
            else if(strncmp(p_data, "SUBSCRIBE", 9) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else
                return APM_L7_IS_NO;

            break;

        case 10:
            if(strncmp(p_data, "DISCONNECT", 10) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else
                return APM_L7_IS_NO;

            break;

        case 11:
            if(strncmp(p_data, "UNSUBSCRIBE", 11) == 0)
                i_ret = FR_DIRECT_CLIENT2SRV;
            else
                return APM_L7_IS_NO;

            break;

        default:
            return APM_L7_IS_NO;

    }

    i_ret_fun = frct_get_direct_known(p_st_conn);
    if( i_ret_fun == FR_DIRECT_UNKNOWN)
    {
        if(i_ret == FR_DIRECT_CLIENT2SRV)
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
        else
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
    }

    return APM_L7_IS_YES;

}

/*!
 * stomp私有数据创建
 *
 *
 *
 * \return p_st_private:成功\n
 *         NULL:失败
 *
 */
FR_STATIC L7session_stomp_private* __stomp_session_private_create(void)
{
    L7session_stomp_private *p_st_private = NULL;

    p_st_private = (L7session_stomp_private *)frmalloc(sizeof(L7session_stomp_private));
    if(p_st_private == NULL)
        return NULL;

    memset(p_st_private, '\0', sizeof(L7session_stomp_private));

    return p_st_private;

}


/*!
 * session数据上报
 *
 * \p_st_body_data               (上报链表)
 * \p_st_private                 (私有数据)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
FR_STATIC int __stomp_session_report(Frreport_body_data *p_st_body_data, L7session_stomp_private *p_st_private)
{
    int i_ret = 0;
    char *p_report_title = NULL;
    int i_tmp_len = 0;

    if(p_st_body_data == NULL || p_st_private == NULL)
        return FR_FAIL;

    if(p_st_private->st_login_timestamp.tv_sec)
    {
        if(p_st_private->p_user_name)
        {
            if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_USERNAME, p_st_private->p_user_name) == FR_FAIL)
                return FR_FAIL;
        }
        else
        {
            if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_USERNAME, "\0") == FR_FAIL)
                return FR_FAIL;
        }

        if(frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_ID, p_st_private->arr_session_id) == FR_FAIL)
            return FR_FAIL;

        if(frreport_body_l7_add_timeval(p_st_body_data, APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP, &p_st_private->st_login_timestamp) == FR_FAIL)
            return FR_FAIL;
    }

    if(p_st_private->p_server)
    {
        i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_SESSION_SERVER, p_st_private->p_server);
        if(i_ret == FR_FAIL)
            return FR_FAIL;
    }

    if(p_st_private->p_title)
    {
        i_tmp_len = strlen(p_st_private->p_title) + 20;
        p_report_title = (char *)frmalloc(i_tmp_len);
        if(p_report_title == NULL)
            return FR_FAIL;

        if(p_st_private->is_topic)
        {
            i_ret = frreport_body_l7_add_str(p_st_body_data, "session.mq.topic", p_st_private->p_title);
            if(i_ret == FR_FAIL)
                return FR_FAIL;
        }
        else
        {
            i_ret = frreport_body_l7_add_str(p_st_body_data, "session.mq.queue", p_st_private->p_title);
            if(i_ret == FR_FAIL)
                return FR_FAIL;
        }

        if(p_st_private->i_use_request)
        {
            if(p_st_private->i_mess_type)
                snprintf(p_report_title, i_tmp_len, "PUT %s", p_st_private->p_title);
            else
            {
                snprintf(p_report_title, i_tmp_len, "SUB %s", p_st_private->p_title);

                i_ret = frreport_body_l7_add_str(p_st_body_data, "subscription.mq.topic", p_st_private->p_title);
                if(i_ret == FR_FAIL)
                    return FR_FAIL;
            }
        }
        else
        {
            snprintf(p_report_title, i_tmp_len, "NOTIFY %s", p_st_private->p_title);
        }

        i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, p_report_title);
        frfree(p_report_title);
        if(i_ret == FR_FAIL)
            return FR_FAIL;

    }
    else
    {
        if(p_st_private->i_use_request)
        {
            if(p_st_private->i_mess_type)
                i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, "PUT");
            else
                i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, "SUB");
        }
        else
            i_ret = frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, "NOTIFY");
    }

    return FR_SUCC;

}

/*!
 * 私有信息初始化
 *
 * \p_private_session             (stomp的私有session数据)
 *
 * \return FR_FAIL:失败\n
 *         FR_SUCC:成功
 *
 */
FR_STATIC int __stomp_session_reset(void *p_private_session)
{
    L7session_stomp_private *p_st_private = (L7session_stomp_private* )p_private_session;

    if(p_st_private)
    {
        if(p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if(p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if(p_st_private->p_lst_comm_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_comm_tmp);

        if(p_st_private->p_lst_req_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_req_tmp);

        if(p_st_private->p_lst_mq_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_mq_tmp);

        if(p_st_private->p_str_pre)
            frstr_free(&p_st_private->p_str_pre);

        if(p_st_private->p_str_mess)
            frstr_free(&p_st_private->p_str_mess);

        if(p_st_private->p_title)
        {
            frfree(p_st_private->p_title);
            p_st_private->p_title = NULL;
        }

        p_st_private->i_action = 0;
        p_st_private->i_report = 0;
        p_st_private->i_data_len = 0;
        p_st_private->i_response_required = 0;
        p_st_private->i_mess_type = 0;
        p_st_private->is_topic = 0;
        memset(&p_st_private->st_l4_trans, 0x00, sizeof(L4_transaction));

    }

    return FR_SUCC;
}


/*!
 * stomp req 的packet解析
 *
 * \p_st_conn                (入力链接信息)
 * \p_st_packet             (入力packet信息)
 * \p_st_hash_report         (保存Frreport_data)
 *
 * \return APM_L7_ANALYZE_SUCC:成功\n
 *         APM_L7_ANALYZE_TODO:数据未结束\n
 *         APM_L7_ANALYZE_FAIL:失败
 *
 */
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = 0;
    L7session_stomp_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    char *p_data_in = NULL;
//    char *p_data_in_tmp = NULL;
    int i_data_len = 0;
    unsigned long ul_tmp = 0;
    Frreport_data *p_st_report_data = NULL;
    unsigned int ui_payload_len = 0;
    char arr_info[1024];

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    i_data_len = p_st_packet->ui_payload_len;
    p_data_in = p_st_packet->p_payload;
    p_st_private = (L7session_stomp_private *)p_st_session->p_session_private;
    p_st_private->ui_all_len += i_data_len;

RESTART:
    //获取数据
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if(p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    //request
    p_st_private->i_use_request = FR_YES;

    //第一个包  创建private 数据
    if(p_st_l4_trans->st_request_time_first_byte.tv_sec == 0
        && p_st_l4_trans->st_request_time_first_byte.tv_usec == 0)
    {
        //创建链表
        if(p_st_private->p_st_body_data_req == NULL)
        {
            p_st_private->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
            if(p_st_private->p_st_body_data_req == NULL)
                return APM_L7_ANALYZE_FAIL;
        }
    }

//    if(p_st_private->p_str_pre)
//    {
//        i_data_len += p_st_private->p_str_pre->ui_len;
//        p_data_in_tmp = frmalloc(i_data_len + 1);
//        if(p_data_in_tmp == NULL)
//            return APM_L7_ANALYZE_FAIL;
//
////        snprintf(p_data_in_tmp, p_st_private->p_str_pre->ui_len + 1, "%s", p_st_private->p_str_pre->p_str);
//        memcpy(p_data_in_tmp, p_st_private->p_str_pre->p_str, p_st_private->p_str_pre->ui_len);
////        snprintf(p_data_in_tmp + p_st_private->p_str_pre->ui_len, i_data_len + 1, "%s", p_data_in);
//        memcpy(p_data_in_tmp + p_st_private->p_str_pre->ui_len, p_data_in, ui_payload_len);
//        frstr_free (&p_st_private->p_str_pre);
//        p_data_in = p_data_in_tmp;
//
//    }

    i_ret = stomp_parse(&p_data_in, &i_data_len, p_st_private->p_st_body_data_req, p_st_private);
//    if(p_data_in_tmp)
//    {
//        frfree(p_data_in_tmp);
//        p_data_in_tmp = NULL;
//    }

    if(p_st_private->i_flag_data_type)
    {
        if(p_st_private->i_flag_data_type == FRLOGOUT_END)
        {

            if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
                snprintf(arr_info, sizeof(arr_info), "%s logout", p_st_private->p_user_name);
            else
                snprintf(arr_info, sizeof(arr_info), "logout");

            p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGOUT, arr_info, &p_st_packet->st_timestamp);

            if (p_st_report_data)
            {
                if(frreport_send(g_p_apm_context, &p_st_report_data) == FR_FAIL)
                {
                    frreport_data_free(&p_st_report_data);
                    return APM_L7_ANALYZE_FAIL;
                }
            }
            frreport_body_free (&p_st_private->p_st_body_data_req);
            return APM_L7_ANALYZE_SET_REQ (APM_L7_ANALYZE_SUCC);
        }
        else if(p_st_private->i_flag_data_type)
        {
            p_st_private->st_login_timestamp.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_private->st_login_timestamp.tv_usec = p_st_packet->st_timestamp.tv_usec;
            fruuid(p_st_private->arr_session_id);
        }

        p_st_private->i_flag_data_type = 0;
    }



    if(p_st_private->i_report)
    {
        //L4 信息统计
        // st_request_time_first_byte
        if(p_st_l4_trans->st_request_time_first_byte.tv_sec == 0)
        {
            // st_request_time_first_byte
            p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

            //seq ++
            p_st_private->ul_seq = frct_seq_increase(p_st_conn);

            //st_request_time
            p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

            /* 请求的字节数 */
            if(i_data_len == 0)
                p_st_l4_trans->l_request_bytes += ui_payload_len;
            else
                p_st_l4_trans->l_request_bytes += ui_payload_len - i_data_len;
        }

        if(i_ret == APM_L7_ANALYZE_SUCC)
        {
            //session 信息上报
            if(__stomp_session_report(p_st_private->p_st_body_data_req, p_st_private) == FR_FAIL)
                goto ERROR;

            //信息上报
            if(frreport_body_l7_add_int(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ISRESPREQUIRED, p_st_private->i_response_required) == FR_FAIL)
                goto ERROR;

            if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
                goto ERROR;

            if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
                goto ERROR;

            if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
                goto ERROR;

            ul_tmp = frtime_diff(&p_st_l4_trans->st_request_time_first_byte, &p_st_l4_trans->st_request_time);
            if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
                goto ERROR;

            if(frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, (long)(p_st_private->ui_all_len - (unsigned int)i_data_len)) == FR_FAIL)
                goto ERROR;
            p_st_private->ui_all_len = (unsigned int)i_data_len;

            if(p_st_private->i_mess_type)
                p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
            else
                p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_SUB);


            if(p_st_report_data == NULL)
                goto ERROR;

            p_st_private->p_lst_comm_tmp = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
            if(p_st_private->p_lst_comm_tmp == NULL)
                goto ERROR;

            p_st_private->p_lst_req_tmp = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
            if(p_st_private->p_lst_req_tmp == NULL)
                goto ERROR;

            if(p_st_private->is_topic)
            {
                p_st_private->p_lst_mq_tmp = FRREPORT_BODY_L7LIST_CLONE_MQ(p_st_private->p_st_body_data_req);
                if(p_st_private->p_lst_mq_tmp == NULL)
                    goto ERROR;
            }

            if(frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
                goto ERROR;
            p_st_private->p_st_body_data_req = NULL;

            if(frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
                goto ERROR;

        }

    }

    if(i_ret == APM_L7_ANALYZE_SUCC)
    {
        if(p_st_private->i_response_required == 0)
            __stomp_session_reset(p_st_private);
        p_st_private->i_action = 0;

        //多个send 情况
        if(i_data_len)
        {
            __stomp_session_reset(p_st_private);
            goto RESTART;
        }

        p_st_private->ui_all_len = 0;
        return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
    }

    return i_ret;

ERROR:
    if(p_st_report_data)
        frreport_data_free(&p_st_report_data);

    if(p_st_private->p_lst_comm_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_comm_tmp);

    if(p_st_private->p_lst_req_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_req_tmp);

    if(p_st_private->p_lst_mq_tmp)
        frreport_body_l7list_free(&p_st_private->p_lst_mq_tmp);

    return APM_L7_ANALYZE_FAIL;


}

/*!
 * stomp resp 的packet解析
 *
 * \p_st_conn                (入力链接信息)
 * \p_st_packet             (入力packet信息)
 * \p_st_hash_report         (保存Frreport_data)
 *
 * \return APM_L7_ANALYZE_SUCC:成功\n
 *         APM_L7_ANALYZE_TODO:数据未结束\n
 *         APM_L7_ANALYZE_FAIL:失败
 *
 */
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = 0;
    L7session_stomp_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    char *p_data_in = NULL;
//    char *p_data_in_tmp = NULL;
    int i_data_len = 0;
    unsigned long ul_tmp = 0;
    Frreport_data *p_st_report_data = NULL;
    char arr_info[1024];

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    i_data_len = p_st_packet->ui_payload_len;
    p_data_in = p_st_packet->p_payload;

    p_st_private = (L7session_stomp_private *)p_st_session->p_session_private;
    p_st_private->ui_all_len += p_st_packet->ui_payload_len;

RESTART:

    p_st_l4_trans = &(p_st_private->st_l4_trans);
    p_st_private->i_use_request = FR_NO;

    if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0)
    {
        //创建链表
        if(p_st_private->p_st_body_data_resp == NULL)
        {
            p_st_private->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
            if(p_st_private->p_st_body_data_resp == NULL)
                return APM_L7_ANALYZE_FAIL;
        }
    }

//    if(p_st_private->p_str_pre)
//    {
//        i_data_len += p_st_private->p_str_pre->ui_len;
//        p_data_in_tmp = frmalloc(i_data_len + 1);
//        if(p_data_in_tmp == NULL)
//            return APM_L7_ANALYZE_FAIL;
//
////        snprintf(p_data_in_tmp, p_st_private->p_str_pre->ui_len + 1, "%s", p_st_private->p_str_pre->p_str);
//        memcpy(p_data_in_tmp, p_st_private->p_str_pre->p_str, p_st_private->p_str_pre->ui_len);
////        snprintf(p_data_in_tmp + p_st_private->p_str_pre->ui_len, i_data_len + 1, "%s", p_data_in);
//        memcpy(p_data_in_tmp + p_st_private->p_str_pre->ui_len, p_data_in, ui_payload_len);
//        p_data_in = p_data_in_tmp;
//        frstr_free (&p_st_private->p_str_pre);
//    }

    i_ret = stomp_parse(&p_data_in, &i_data_len, p_st_private->p_st_body_data_resp, p_st_private);
    if(p_st_private->i_flag_data_type)
    {
        if(p_st_private->i_flag_data_type == FRLOGIN_SUCC)
        {
            if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
                snprintf(arr_info, sizeof(arr_info), "%s login", p_st_private->p_user_name);
            else
                snprintf(arr_info, sizeof(arr_info), "login");

            p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON, arr_info, &p_st_packet->st_timestamp);
        }
        else if (p_st_private->i_flag_data_type == FRLOGIN_FAIL)
        {
            if (p_st_private->p_user_name != NULL && *p_st_private->p_user_name != '\0')
                snprintf(arr_info, sizeof(arr_info), "%s login reject", p_st_private->p_user_name);
            else
                snprintf(arr_info, sizeof(arr_info), "login reject");

            p_st_report_data = frreport_update_create(p_st_conn, APM_REPORT_UPDATE_LOGON_REJECT, arr_info, &p_st_packet->st_timestamp);
        }

        if (p_st_report_data)
        {
            if(frreport_send(g_p_apm_context, &p_st_report_data) == FR_FAIL)
            {
                frreport_data_free(&p_st_report_data);
                return APM_L7_ANALYZE_FAIL;
            }
        }

        p_st_private->i_flag_data_type = 0;

        frreport_body_free (&p_st_private->p_st_body_data_req);
        __stomp_session_reset(p_st_private);

        if(i_data_len)
            goto RESTART;

        p_st_private->ui_all_len = 0;
        return APM_L7_ANALYZE_SET_RESP (APM_L7_ANALYZE_SUCC);

    }


    if(p_st_private->i_report)
    {
        //st_response_time_first_byte
        p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        //st_response_time
        p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;
        /* 请求的字节数 */

        if(i_ret == APM_L7_ANALYZE_SUCC)
        {
            if(p_st_private->ul_seq == 0 || p_st_private->p_lst_comm_tmp == NULL)
                p_st_private->ul_seq = frct_seq_increase(p_st_conn);

            //只有response
            if(p_st_private->p_lst_comm_tmp == NULL)
            {
                if(frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_resp, p_st_conn) == FR_FAIL)
                    goto ERROR;

                if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, 0) == FR_FAIL)
                    goto ERROR;

                //session
                if(__stomp_session_report(p_st_private->p_st_body_data_resp, p_st_private) == FR_FAIL)
                    goto ERROR;

            }
            else
            {
                //comm
                if(FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_comm_tmp) == FR_FAIL)
                    goto ERROR;

                //把req数据链表添加到resp中
                if(FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_req_tmp) == FR_FAIL)
                    goto ERROR;

                if(p_st_private->is_topic)
                {
                    if(FRREPORT_BODY_L7LIST_SET_MQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_mq_tmp) == FR_FAIL)
                        goto ERROR;
                }

                ul_tmp = frtime_diff(&p_st_l4_trans->st_request_time, &p_st_l4_trans->st_response_time_first_byte);
                if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
                    goto ERROR;

            }

            if(frreport_body_l7_add_int(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_CODE, 0) == FR_FAIL)
                goto ERROR;

            if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
                goto ERROR;

            if(frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
                goto ERROR;

            ul_tmp = frtime_diff(&p_st_l4_trans->st_response_time_first_byte, &p_st_l4_trans->st_response_time);
            if(frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
                goto ERROR;

            if(frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, (long)(p_st_private->ui_all_len - (unsigned int)i_data_len)) == FR_FAIL)
                goto ERROR;
            p_st_private->ui_all_len = (unsigned int)i_data_len;

            if(p_st_private->i_mess_type)
                p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_NOTIFY);
            else
                p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);

            if(p_st_report_data == NULL)
                goto ERROR;

            if(frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
                goto ERROR;
            p_st_private->p_st_body_data_resp = NULL;

            if(frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
                goto ERROR;

        }

    }
    if(i_ret == APM_L7_ANALYZE_SUCC)
    {
        __stomp_session_reset(p_st_private);

        if(i_data_len)
            goto RESTART;

        p_st_private->ui_all_len = 0;
        return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
    }

    return i_ret;

ERROR:
    if(p_st_report_data)
        frreport_data_free(&p_st_report_data);

    return APM_L7_ANALYZE_FAIL;

}



/*!
 * stomp的packet解析
 *
 * \p_st_conn                (入力链接信息)
 * \p_st_packet             (入力packet信息)
 * \p_st_hash_report         (保存Frreport_data)
 *
 * \return APM_L7_ANALYZE_SUCC:成功\n
 *         APM_L7_ANALYZE_TODO:数据未结束\n
 *         APM_L7_ANALYZE_FAIL:失败
 *
 */
int stomp_analysis(Conntrack *p_st_conn
                  , Apm_packet *p_st_packet
                  , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_session *p_st_session = NULL;

    if(p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin syn 包  销毁私有数据
    if(p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        stomp_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //p_session_private   分配内存
    if(p_st_session->p_session_private == NULL)
    {
        p_st_session->p_session_private = __stomp_session_private_create();
        //内存分配失败
        if(p_st_session->p_session_private == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    //request
    if(p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn,p_st_packet,p_st_hash_report,p_st_session);
        if(i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }
    else//response
    {
        i_ret = __resp_data_analysis(p_st_conn,p_st_packet,p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }

ERROR:
    stomp_session_destroy((void *)(p_st_session->p_session_private));
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;

}

/*!
 * 私有信息销毁
 *
 * \p_private_session   (stomp的私有session数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int stomp_session_destroy(void *p_private_session)
{
    L7session_stomp_private *p_st_private = (L7session_stomp_private* )p_private_session;

    if(p_st_private)
    {
        if(p_st_private->p_user_name)
            frfree(p_st_private->p_user_name);

        if(p_st_private->p_server)
            frfree(p_st_private->p_server);

        if(p_st_private->p_title)
            frfree(p_st_private->p_title);

        if(p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if(p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if(p_st_private->p_lst_comm_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_comm_tmp);

        if(p_st_private->p_lst_req_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_req_tmp);

        if(p_st_private->p_lst_mq_tmp)
            frreport_body_l7list_free(&p_st_private->p_lst_mq_tmp);

        if(p_st_private->p_str_pre)
            frstr_free(&p_st_private->p_str_pre);

        if(p_st_private->p_str_mess)
            frstr_free(&p_st_private->p_str_mess);

        frfree(p_st_private);
    }

    return FR_SUCC;
}

